package impl

import (
	"context"
	"fmt"
	"vblog/apps/blog"
	"vblog/common"
	"vblog/conf"
	"vblog/ioc"

	"dario.cat/mergo"
	"gorm.io/gorm"
)

var _ blog.Service = &BlogServiceImpl{}

// var ctx context.Context

type BlogServiceImpl struct {
	db *gorm.DB
}

func init() {
	ioc.Controller.Registry(blog.AppName, &BlogServiceImpl{})
}

func (b *BlogServiceImpl) Init() error {
	b.db = conf.C().MySQL.GetDB()
	return nil
}

func (b *BlogServiceImpl) BlogModel() *gorm.DB {
	return b.db.Model(&blog.Blog{})
}

func (b *BlogServiceImpl) CreateBlog(ctx context.Context, in *blog.CreateBlogRequest) (*blog.Blog, error) {

	if err := in.Validate(); err != nil {
		return nil, err
	}

	// TODO 这里作者从user中获取
	// in.Author =
	ins := blog.NewBlog()
	ins.CreateBlogRequest = in
	// ins.CreateBy=
	// ins:=
	if err := b.BlogModel().WithContext(ctx).Create(ins).Error; err != nil {
		return nil, err
	}

	return ins, nil
}
func (b *BlogServiceImpl) QueryBlog(ctx context.Context, in *blog.QueryBlogRequest) (*blog.BlogSet, error) {

	set := blog.NewBlogSet()

	query := b.BlogModel().WithContext(ctx)
	if in.Keywords != "" {
		query = query.Where("title LIKE ?", fmt.Sprintf("%%%s%%", in.Keywords))
	}

	if err := query.Count(&set.Total).Error; err != nil {
		return nil, err
	}

	if err := query.Limit(in.PageSize).Offset(in.Offset()).Find(&set.Items).Error; err != nil {
		return nil, err
	}

	return set, nil
}
func (b *BlogServiceImpl) UpdateBlog(ctx context.Context, in *blog.UpdateBlogRequest) (*blog.Blog, error) {

	ins, err := b.DescribeBlog(ctx, blog.NewDescribeBlogRequest(in.BlogId))
	if err != nil {
		return nil, err
	}

	// ins := blog.NewBlog()

	switch in.UpdateMode {
	case common.UPDATE_MODE_PATCH:
		// 检查是否为空 validate
		err := mergo.MergeWithOverwrite(ins.CreateBlogRequest, in.CreateBlogRequest)
		if err != nil {
			return nil, err
		}
	case common.UPDATE_MODE_PUT:
		ins.CreateBlogRequest = in.CreateBlogRequest

	}

	// 校验
	if err := ins.CreateBlogRequest.Validate(); err != nil {
		return nil, err
	}

	if err := b.BlogModel().WithContext(ctx).Where("id = ?", in.BlogId).Save(ins).Error; err != nil {
		return nil, err
	}
	return ins, nil
}
func (b *BlogServiceImpl) DescribeBlog(ctx context.Context, in *blog.DescribeBlogRequest) (*blog.Blog, error) {

	ins := blog.NewBlog()
	if err := b.BlogModel().WithContext(ctx).Where("id = ?", in.BlogId).First(ins).Error; err != nil {
		return nil, err
	}
	return ins, nil
}

func (b *BlogServiceImpl) DeleteBlog(ctx context.Context, in *blog.DeleteBlogRequest) (*blog.Blog, error) {

	ins := blog.NewBlog()
	if err := b.BlogModel().WithContext(ctx).Where("id = ?", in.BlogId).Delete(ins).Error; err != nil {
		return nil, err
	}
	return ins, nil
}

func (b *BlogServiceImpl) UpdateBlogStatus(ctx context.Context, in *blog.UpdateBlogStatusRequest) (*blog.Blog, error) {

	ins, err := b.DescribeBlog(ctx, blog.NewDescribeBlogRequest(in.BlogId))
	if err != nil {
		return nil, err
	}

	ins.ChangeBlogStatusRequest = in.ChangeBlogStatusRequest
	in.UpdateStatus(in.Status)

	if err := b.db.WithContext(ctx).Where("id = ?", in.BlogId).Updates(ins).Error; err != nil {
		return nil, err
	}
	return ins, nil
}
